﻿Public Structure Line
    Public PointA As Vector2
    Public PointB As Vector2

    Public Shared Function AreLinesParallel(line1 As Line, line2 As Line) As Boolean
        Return line1.Slope = line2.Slope
    End Function

    Public Shared Function AreLinesPerpendicular(line1 As Line, line2 As Line) As Boolean
        Dim delta As Single = -1 / line1.Slope
        Return delta = line2.Slope
    End Function

    Public Shared Function GetIntersection(line1 As Line, line2 As Line) As Vector2
        Dim x As Single
        x = (((((line1.PointA.X * line1.PointB.Y)) - (line1.PointA.Y * line1.PointB.X)) * (line2.PointA.X - line2.PointB.X)) - ((line1.PointA.X - line1.PointB.X) * ((line2.PointA.X * line2.PointB.Y) - (line2.PointA.Y * line2.PointB.X)))) /
            (((line1.PointA.X - line1.PointB.X) * (line2.PointA.Y - line2.PointB.Y)) - ((line1.PointA.Y - line1.PointB.Y) * (line2.PointA.X - line2.PointB.X)))
        Dim y As Single
        y = (((((line1.PointA.X * line1.PointB.Y)) - (line1.PointA.Y * line1.PointB.X)) * (line2.PointA.Y - line2.PointB.Y)) - ((line1.PointA.Y - line1.PointB.Y) * ((line2.PointA.X * line2.PointB.Y) - (line2.PointA.Y * line2.PointB.X)))) /
            (((line1.PointA.X - line1.PointB.X) * (line2.PointA.Y - line2.PointB.Y)) - ((line1.PointA.Y - line1.PointB.Y) * (line2.PointA.X - line2.PointB.X)))
        Return New Vector2(x, y)
    End Function

    Public ReadOnly Property LeftPoint As Vector2
        Get
            If PointB.X > PointA.X Then
                Return PointB
            End If
            Return PointA
        End Get
    End Property

    Public ReadOnly Property RightPoint As Vector2
        Get
            If PointB.X < PointA.X Then
                Return PointB
            End If
            Return PointA
        End Get
    End Property

    Public ReadOnly Property BottomPoint As Vector2
        Get
            If PointB.Y > PointA.Y Then
                Return PointB
            End If
            Return PointA
        End Get
    End Property

    Public ReadOnly Property TopPoint As Vector2
        Get
            If PointB.Y < PointA.Y Then
                Return PointB
            End If
            Return PointA
        End Get
    End Property

    Public ReadOnly Property Center As Vector2
        Get
            Return New Vector2((PointA.X + PointB.X) / 2, (PointA.Y + PointB.Y) / 2)
        End Get
    End Property

    Public ReadOnly Property Length As Single
        Get
            Return Vector2.GetDistance(PointA, PointB)
        End Get
    End Property

    Public ReadOnly Property Angle As Single
        Get
            Return Vector2.GetAngleTo(PointA, PointB)
        End Get
    End Property

    Public ReadOnly Property Slope As Single
        Get
            Return Vector2.GetSlope(PointA, PointB)
        End Get
    End Property

    Public Function GetIntersection(other As Line) As Vector2
        Return GetIntersection(Me, other)
    End Function

    Public Function IsParallelTo(other As Line) As Boolean
        Return AreLinesParallel(Me, other)
    End Function

    Public Function IsPerpendicularTo(other As Line) As Boolean
        Return AreLinesPerpendicular(Me, other)
    End Function

    Public Sub New(a As Vector2, b As Vector2)
        PointA = a
        PointB = b
    End Sub

    Public Sub New(x1 As Single, y1 As Single, x2 As Single, y2 As Single)
        PointA = New Vector2(x1, y1)
        PointB = New Vector2(x2, y2)
    End Sub

    Public Overrides Function Equals(obj As Object) As Boolean
        If TypeOf obj Is Line Then
            Dim other As Line = DirectCast(obj, Line)
            Return (PointA = other.PointA AndAlso PointB = other.PointB) OrElse (PointA = other.PointB AndAlso PointB = other.PointA)
        End If
        Return False
    End Function

    Public Overrides Function ToString() As String
        Return String.Format("({0}-{1})", PointA, PointB)
    End Function

    Public Sub Transform(amount As Vector2)
        PointA -= (amount / 2)
        PointB += (amount / 2)
    End Sub

    Public Sub Translate(amount As Vector2)
        PointA += amount
        PointB += amount
    End Sub
End Structure